/* Copyright 2020, 2023-2024 NXP
 *
 * NXP Confidential. This software is owned or controlled by NXP and may only
 * be used strictly in accordance with the applicable license terms.  By
 * expressly accepting such terms or by downloading, installing, activating
 * and/or otherwise using the software, you are agreeing that you have read,
 * and that you agree to comply with and are bound by, such license terms.  If
 * you do not agree to be bound by the applicable license terms, then you may
 * not retain, install, activate or otherwise use the software.
 */

#include "phUwb_BuildConfig.h"

#if !defined(UWBIOT_APP_BUILD__DEMO_STANDALONE_COMMON)
#include "UWBIOT_APP_BUILD.h"
#endif

#if defined(UWBIOT_APP_BUILD__DEMO_PNP)

#include "board.h"
#include "fsl_lpuart_edma.h"
#include "fsl_lpuart.h"
#include "fsl_adapter_uart.h"
#include "Uwb_Vcom_Pnp.h"
#include <stdio.h>
#include <stdbool.h>
#include "phOsalUwb.h"
#include <UwbPnpInternal.h>
#include "phUwbStatus.h"
#include "phNxpLogApis_App.h"
#include "UwbPnpInternal.h"
//#include "fsl_wwdt.h"
#include "UwbApi_Utility.h"

#include "board_comp.h"
#include "fsl_component_serial_manager.h"
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/* LPUART user callback */
void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData);

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*******************************************************************************
 * Definitions
 ******************************************************************************/
/*${macro:start}*/
#define DEMO_LPUART                 LPUART0
#define DEMO_LPUART_CLKSRC   		kCLOCK_Lpuart0
#define DEMO_LPUART_CLK_FREQ        BOARD_DEBUG_UART_CLK_FREQ
//#define LPUART_TX_DMA_CHANNEL       2U
//#define LPUART_RX_DMA_CHANNEL       3U
//#define DEMO_LPUART_TX_EDMA_CHANNEL 32U
//#define DEMO_LPUART_RX_EDMA_CHANNEL 31U

#define DEMO_LPUART_BAUDRATE 		460800 //115200

#define ECHO_BUFFER_LENGTH 			8
#define FTDI_BUFFER_SIZE     		256

#if (cPWR_UsePowerDownMode) || (cPWR_FullPowerDownMode)
#pragma message( \
    "DEMO_USART_BAUDRATE = 3Mbps : Disable low power mode from app_preinclude.h file & perform clean build AND always use release build to work with higher baud-rate")
#endif //(cPWR_UsePowerDownMode) || (cPWR_FullPowerDownMode)

#define UART_HEADER_SIZE 			3

/*FTDI has TX/Rx FIFO of 512 Bytes */
#define MAX_TRANSFER_COUNT 			512

#define LPUART_RCV_HDR_NON_BLOCKING(BUFFER, SIZE, RCVD_BYTES_PTR) \
    rcvXfer.data     = BUFFER;                                   \
    rcvXfer.dataSize = SIZE;                                     \
    LPUART_TransferReceiveNonBlocking(DEMO_LPUART, &g_lpuartHandle, &rcvXfer,NULL);

/*${macro:end}*/

//lpuart_edma_handle_t g_lpuartEdmaHandle;
lpuart_handle_t g_lpuartHandle;
//edma_handle_t g_lpuartTxEdmaHandle;
//edma_handle_t g_lpuartRxEdmaHandle;
void *mHifRspSem = NULL;
static uint8_t buffer[4096];
static lpuart_transfer_t rcvXfer;
static lpuart_transfer_t sendXfer;

volatile bool mError = FALSE;
extern uint8_t uwb_ota_init;

/*******************************************************************************
 * Code
 ******************************************************************************/
static void (*LpuartRcvCb)(uint8_t *, uint32_t *);
static bool TxIdle_flag = true;
/* LPUART user callback */
void LPUART_UserCallback(LPUART_Type *base, lpuart_handle_t *handle, status_t status, void *userData)
{
	//PRINTF("LPUART_UserCallback\r\n");
	//PRINTF("status = %d\r\n",status);
    userData = userData;

    if (kStatus_LPUART_TxIdle == status)
    {
    	//PRINTF("LPUART_TxIdle\r\n");
        (void)phOsalUwb_ProduceSemaphore(mHifRspSem);
    }

    if (kStatus_LPUART_RxIdle == status)
    {
    	uint32_t payloadLength = (buffer[UART_HEADER_SIZE - 2] << (8 * 1)) | (buffer[UART_HEADER_SIZE - 1] << (8 * 0));

        if (payloadLength > 0) {
            if (payloadLength < (FTDI_BUFFER_SIZE - UART_HEADER_SIZE)) {
                // uwb_pnp_reload_timer();
            }
            else if (payloadLength > (sizeof(buffer) - UART_HEADER_SIZE)) {
                /* protocol error */

            	if (uwb_ota_init == 1) {
            		PRINTF("uart protocol error but not reboot \n ");
            	} else {
            		PRINTF("uwb_pnp_board_protocol_error_handler_1\r\n");
            		uwb_pnp_board_protocol_error_handler();
            	}
            }

            status = LPUART_ReadBlocking(base, (&buffer[UART_HEADER_SIZE]), payloadLength);
        }
        payloadLength += UART_HEADER_SIZE;
        if (LpuartRcvCb) {
        	LpuartRcvCb(buffer, &payloadLength);
        }
        phOsalUwb_SetMemory(buffer, 0, sizeof(buffer));

        LPUART_RCV_HDR_NON_BLOCKING(buffer, UART_HEADER_SIZE, NULL);
    }
}


void Uwb_lpuart_Init(void (*rcvCb)(uint8_t *, uint32_t *))
{
    /* This semaphore is signaled when ACK is received for the Bulkin Operations(USB Write) for sending UCI resp from
     * Rhodes*/
    if (phOsalUwb_CreateBinSem(&mHifRspSem) != UWBSTATUS_SUCCESS) {
        PRINTF("Error: main, could not create semaphore mHifRspSem\n");
        while (1)
            ;
    }

    BOARD_InitAppConsole();

    lpuart_config_t lpuartConfig;

    //edma_config_t userConfig = {0};

    LPUART_GetDefaultConfig(&lpuartConfig);
    lpuartConfig.baudRate_Bps = DEMO_LPUART_BAUDRATE;
    lpuartConfig.enableTx     = true;
    lpuartConfig.enableRx     = true;

    LpuartRcvCb = rcvCb;

    LPUART_Init(DEMO_LPUART, &lpuartConfig, BOARD_APP_UART_CLK_FREQ);

    /* Init the EDMA module */
//    EDMA_GetDefaultConfig(&userConfig);

//    EDMA_Init(DMA0, &userConfig);

//    EDMA_CreateHandle(&g_lpuartTxEdmaHandle, DMA0, LPUART_TX_DMA_CHANNEL);
//    EDMA_CreateHandle(&g_lpuartRxEdmaHandle, DMA0, LPUART_RX_DMA_CHANNEL);

//#if defined(FSL_FEATURE_EDMA_HAS_CHANNEL_MUX) && FSL_FEATURE_EDMA_HAS_CHANNEL_MUX
//    EDMA_SetChannelMux(DMA0, LPUART_TX_DMA_CHANNEL, DEMO_LPUART_TX_EDMA_CHANNEL);
//    EDMA_SetChannelMux(DMA0, LPUART_RX_DMA_CHANNEL, DEMO_LPUART_RX_EDMA_CHANNEL);
//#endif

//    NVIC_SetPriority(DMA0_CH2_IRQn, 4+2);
//    NVIC_SetPriority(DMA0_CH3_IRQn, 4+3);

    NVIC_SetPriority(LPUART0_IRQn, 4+3);


    /* Create LPUART DMA handle. */
    LPUART_TransferCreateHandle(DEMO_LPUART, &g_lpuartHandle, LPUART_UserCallback, NULL);
    LPUART_RCV_HDR_NON_BLOCKING(buffer, UART_HEADER_SIZE, &rxReceivedBytes);

}


uint32_t transmitToLpuart(uint8_t *pData, size_t size)
{
    status_t status;
    if (size == 0) {
        return 1;
    }

    if (size <= DMA_MAX_TRANSFER_COUNT) {
        sendXfer.data     = pData;
        sendXfer.dataSize = size;
        status            = LPUART_TransferSendNonBlocking(DEMO_LPUART, &g_lpuartHandle, &sendXfer);
        if (status == kStatus_Success) {
            if (phOsalUwb_ConsumeSemaphore_WithTimeout(mHifRspSem, MAX_UWBS_SPI_TRANSFER_TIMEOUT) !=
                UWBSTATUS_SUCCESS) {
                PRINTF("transmitToLpuart timeout");
                return kStatus_Fail;
            }
        }
    }
	return (uint32_t)kStatus_Success;
}

void uwb_pnp_board_protocol_error_handler()
{
	PRINTF("Protocol error! System resetting...\r\n");
	NVIC_SystemReset();
}

#endif // defined(UWBIOT_APP_BUILD__DEMO_PNP)
